﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MenuLib
{
    /// <summary>
    /// The basic menu item to be used in console menus.
    /// 1) Is capable of drawing itself on cosole window.
    /// 2) Has event which occurs when the item is selected
    /// </summary>
    [Serializable]
    public class MenuItem : ISerializable
    {
        /// <summary>
        /// Item identification and display name
        /// </summary>
        private string name;

        /// <summary>
        /// Item display text (long description)
        /// </summary>
        private string text;

        /// <summary>
        /// Item selection text. The selection text format is specific for the menu containing the item.
        /// Item just display's it (see Display method to see how this field used).
        /// </summary>
        private string selectionText;

        /// <summary>
        /// Menu owning the item
        /// </summary>
        private Menu ownerMenu;

        /// <summary>
        /// Initializes a new instance of the MenuItem class with the specified display name.
        /// The item's display text is set to the same value as the name.
        /// </summary>
        /// <param name="name">The display name of the item</param>
        public MenuItem(string name) :
            this(name, name)
        {
        }

        /// <summary>
        /// Initializes a new instance of the MenuItem class with the specified display name and text.
        /// </summary>
        /// <param name="name">The display name of the item</param>
        /// <param name="text">The display text of the item</param>
        public MenuItem(string name, string text)
        {
            Name = name;
            Text = text;
            SelectionText = string.Empty;
        }

        /// <summary>
        /// Gets or sets the display name of the item.
        /// </summary>
        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        /// <summary>
        /// Gets or sets the display text of the item.
        /// </summary>
        public string Text
        {
            get { return text; }
            set { text = value; }
        }

        /// <summary>
        /// Gets or sets the selection text of the item.
        /// </summary>
        public string SelectionText
        {
            get { return selectionText; }
            set { selectionText = value; }
        }

        /// <summary>
        /// Gets or sets the menu owning the item.
        /// The property is virtual, so subordinate classes may invoke some aditional functionality when
        /// the item is assigned to the menu at set method.
        /// </summary>
        public virtual Menu OwnerMenu
        {
            get { return ownerMenu; }
            set { ownerMenu = value; }
        }

        /// <summary>
        /// Displays the item on cosole window.
        /// </summary>
        public virtual void Display()
        {
            Console.WriteLine("{0} {1} - {2}", SelectionText, Name, Text);
        }

        /// <summary>
        /// Occurs when the item is selected within the owning menu.
        /// </summary>
        public event EventHandler Select;

        /// <summary>
        /// Raises the Select event.
        /// The console menu item represented by this class is totally passive, meaning it is absolutelly
        /// clueless about the fact it is selected. So it is 100% the responsibility of the owning menu
        /// to call this method upon item's selection.
        /// That's the reason this method declared as protected internal
        /// </summary>
        /// <param name="e">empty event arguments: no data neded</param>
        protected internal virtual void OnSelect(EventArgs e)
        {
            if (null != Select)
            {
                Select(this, e);
            }
        }



        #region ISerializable Members

        const string nameValueName = "Name";
        const string textValueName = "Text";
        const string selectionTextValueName = "SelectionText";
        const string ownerMenuValueName = "OwnerMenu";

        public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(nameValueName, Name);
            info.AddValue(textValueName, Text);
            info.AddValue(selectionTextValueName, SelectionText);
            info.AddValue(ownerMenuValueName, OwnerMenu);
        }

        protected MenuItem(SerializationInfo info, StreamingContext context)
        {
            Name = info.GetString(nameValueName);
            Text = info.GetString(textValueName);
            SelectionText = info.GetString(selectionTextValueName);
            ownerMenu = (Menu)info.GetValue(ownerMenuValueName, typeof(Menu));
        }

        #endregion
    }
}
